package org.rency.crawler.common.template;

import org.rency.common.utils.tool.StringUtil;
import org.rency.crawler.common.enums.ReturnCode;
import org.rency.crawler.common.exception.CrawlerException;
import org.rency.crawler.common.exception.CrawlerIllegalException;
import org.rency.crawler.common.exception.NotSupportException;
import org.rency.crawler.common.helper.ValidatorHelper;
import org.rency.crawler.common.request.BaseRequest;
import org.rency.crawler.common.response.BaseResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 描述: Dubbo服务处理模板<br>
 * 最近修改时间:2017/9/7 11:17<br>
 *
 * @author CaiyuRen
 * @version V1.0
 * @since 2017/9/7 11:17
 */
public abstract class DubboServiceTemplate<REQUEST extends BaseRequest, RESPONSE extends BaseResponse, DOMAIN extends BaseRequest, RESULT extends BaseResponse> {

  protected final Logger logger = LoggerFactory.getLogger(this.getClass());

  /**
   * Dubbo服务处理
   * @param request
   * @return
   */
  public RESPONSE execute(REQUEST request){
    logger.info("[DUBBO]请求:[{}]-{}",this.getInterfaceName(),request);
    RESPONSE response = null;
    try{
      /****** 1.参数校验 ******/
      this.validate(request);

      /****** 2.参数转换 ******/
      DOMAIN domain= this.convertor(request);

      /****** 3.服务处理 ******/
      RESULT result = this.doService(domain);

      /****** 4.渲染响应 ******/
      response = this.renderResult(result,request);
    }catch (Exception e){
      response = this.exceptionHandle(e,request);
    }finally {
      logger.info("[DUBBO]请求响应:[{}]-{}",this.getInterfaceName(),response);
    }
    return response;
  }

  /**
   * 获取Dubbo接口名称
   * @return
   */
  protected abstract String getInterfaceName();

  /**
   * 参数校验
   * @param request
   */
  private void validate(REQUEST request){
    ValidatorHelper.validator(request);
    this.innerValidate(request);
  }

  /**
   * 内部校验
   * @param request
   */
  protected abstract void innerValidate(REQUEST request);

  /**
   * 参数转换
   * @param request
   * @return
   */
  protected abstract DOMAIN convertor(REQUEST request);

  /**
   * 服务处理
   * @param domain
   * @return
   */
  protected abstract RESULT doService(DOMAIN domain);

  /**
   * 渲染结果
   * @param result
   * @param request
   * @return
   */
  private RESPONSE renderResult(RESULT result, REQUEST request){
    RESPONSE response = this.createResponse();
    response.setReturnCode(result.getReturnCode());
    response.setReturnMessage(result.getReturnMessage());
    response.setExtension(result.getExtension());
    if(ReturnCode.SUCCESS == result.getReturnCode()){
      this.fillResponse(response,request,result);
    }
    return response;
  }

  /**
   * 填充响应结果
   * @param response
   * @param request
   * @param result
   */
  protected abstract void fillResponse(RESPONSE response,REQUEST request,RESULT result);

  /**
   * 创建响应实例
   * @return
   */
  protected abstract RESPONSE createResponse();

  /**
   * 异常处理
   * @param t
   * @param request
   * @return
   */
  private RESPONSE exceptionHandle(Throwable t,REQUEST request){
    RESPONSE response = this.createResponse();
    if(t instanceof CrawlerIllegalException){
      CrawlerIllegalException ex = (CrawlerIllegalException) t;
      response.setReturnCode(ex.getReturnCode());
      response.setReturnMessage(ex.getDetailMessage());
    }else if(t instanceof IllegalArgumentException){
      IllegalArgumentException ex = (IllegalArgumentException) t;
      response.setReturnCode(ReturnCode.ILLEGAL_VALID);
      response.setReturnMessage(ex.getMessage());
    }else if(t instanceof CrawlerException){
      CrawlerException ex = (CrawlerException) t;
      response.setReturnCode(ex.getReturnCode());
      response.setReturnMessage(ex.getDetailMessage());
    }else if(t instanceof NotSupportException){
      NotSupportException ex = (NotSupportException) t;
      response.setReturnCode(ex.getReturnCode());
      response.setReturnMessage(ex.getDetailMessage());
    }else if(t instanceof Exception){
      Exception ex = (Exception) t;
      response.setReturnCode(ReturnCode.FAIL);
      response.setReturnMessage(StringUtil.abbreviate(ex.getMessage(),500));
    }else{
      response.setReturnCode(ReturnCode.FAIL);
      response.setReturnMessage("未知异常,请联系管理员!");
    }
    return response;
  }

}
